/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2008 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#ifndef INCL_FUN_RECURRENCE
#define INCL_FUN_RECURRENCE
    
#include <sqlite3.h>
#include "base/util/StringBuffer.h"
#include "base/util/ArrayList.h"
#include "Date.h"

using namespace Funambol;

typedef enum {
    daily = 1,
    weekly,
    monthly,
    yearly,
    monthlyTh,
    yearlyTh,
    frequency_empty
}   Frequency;  // to be combined with the RecurrenceType...

class Recurrence {

private:
       
    Frequency frequency;           // frequency 1=daily, 2=weekly, 3=monthly, 4=yearly
    int  interval;                 // interval
    bool noEndDate;                // it means if the recurrence ends or not. If true, the endDate field is 0
    int  occurrences;              // number of occurrences. Retrieverd from the day and occurrence_date arrayList
    
    Date endDate;                  // a string represent the end date/time of the last recurrence day (at 23:59 GMT  time)
                                   // it is 0 if the recurrence has no end. It is the ones used to create the insert in the table
    
    long dayOfWeek;                // it sets the day of week mask. 
    int  monthOfYear;              // it sets the month of year 
    int  dayOfMonth;               // it sets the day of month
    
    Date patternEndDate;           // used in parsing the recurrence object. It stores the date that comes in the vcal. It is used to calculate the
                                   // number of occurrences and to determine the endDate that is written in the db
    
    // specific for iphone client... They are set with default values
    int week_start;
    int count;
    Date cached_end_date;
    StringBuffer cached_end_date_tz;
    StringBuffer specifier;
    int by_month_months;
    
    // used into the windows (outlook and windows mobile) clients
    int  instance;       
    Date patternStartDate;
    Date patternStartTime;
    Date patternEndTime;    
    
    //
    // Note: the following arraylist are filled together and must be used together
    // to fill the Recurrence database row
    //
    /**
    * It contains the list of days the occurrences happen. They are in the right format
    * already for the database. They are used for the insert only (server->client). From client->server
    * It is not needed to know every single occurrence. Actually they are filled differently due
    * to the kind of recurrence. i.e.
    */
    ArrayList day;
    
    /**
    * It contains the list of day+date the occurrences happen. It could be the right format
    * already in the database format. They are string
    */
    ArrayList occurrence_date;        
    
    /**
     * It contains a list that is used by the recurrenceDataConverter formatter that needs
     * to calculate the line of the timezone. It is filled by the recurrencedatastore
     * getRecurrence that gets the information from the subsequent dates of the recurring occurrences
     */
    ArrayList yearsForTimezoneInfo;
    
public:
    
    Recurrence() {
        interval    = 0;
        noEndDate   = false;
        occurrences = 0;
        endDate.setDate(EMPTY_DATE);
        monthOfYear = 0;
        dayOfMonth  = 0;
        
        // used with default values
        week_start  = 1;
        count       = 0;
        cached_end_date.setDate(EMPTY_DATE);
        cached_end_date_tz = "";
        specifier   = "";
        by_month_months = 0;
    
    }
    
    ~Recurrence() {}
    
    void setFrequency(Frequency v)  { frequency = v; }
    Frequency getFrequency()        { return frequency; }       
         
    void setInterval(int v)         { interval = v; }
    int getInterval()               { return interval; }       

    void setMonthOfYear(int v)      { monthOfYear = v; }
    int getMonthOfYear()            { return monthOfYear; }       
        
    void setDayOfMonth(int v)       { dayOfMonth = v; }
    int getDayOfMonth()             { return dayOfMonth; }       
    
    void setDayOfWeek(int v)       { dayOfWeek = v; }
    int getDayOfWeek()             { return dayOfWeek; }       
        
    void setInstance(int v)         { instance = v; }
    int getInstance()               { return instance; }       
   
    /**
    * NOTE: only the date part has to be considered
    */   
    void setPatternStartDate(Date& d) { patternStartDate = d; }
    Date& getPatternStartDate() { return patternStartDate; }    
   
    /**
    * NOTE: only the time part has to be considered
    */   
    void setPatternStartTime(Date& d) { patternStartTime = d; }
    Date& getPatternStartTime() { return patternStartTime; }    

    /**
    * NOTE: only the date part has to be considered
    */      
    void setPatternEndDate(Date& d) { patternEndDate = d; }
    Date& getPatternEndDate() { return patternEndDate; }    
    
    /**
    * NOTE: only the time part has to be considered
    */   
    void setPatternEndTime(Date& d) { patternEndTime = d; }
    Date& getPatternEndTime() { return patternEndTime; }    
    
    void setNoEndDate(bool v) { noEndDate = v; }
    bool getNoEndDate() { return noEndDate; }    
    
    void setOccurrences(int v) { occurrences = v; }
    int getOccurrences() {return occurrences; }       
    
    ArrayList& getDay()                     { return day; }
    ArrayList& getOccurrence_date()         { return occurrence_date; }
    
    ArrayList& getYearsForTimezoneInfo()    { return yearsForTimezoneInfo; }
    
    // Used in the iphone plug-in
    void setEndDate(Date& d)            { endDate = d; }
    Date& getEndDate()                  { return endDate; }
    
    void setWeek_start(int v)           { week_start = v; }
    int getWeek_start()                 { return week_start; }       
    
    void setCount(int v)                { count = v; }
    int getCount()                      {return count; }       
    
    void setCached_end_date(Date& d)    { cached_end_date = d; }
    Date& getCached_end_date()          { return cached_end_date; }
    
    void setCached_end_date_tz(const char* v)   { 
    	if(strlen(v) > 0) {
    		cached_end_date_tz = v;
    	}
    }
    const char* getCached_end_date_tz()         { return cached_end_date_tz; }   
    
    void setSpecifier(const char* v)    { specifier = v; }
    const char* getSpecifier()          { return specifier; }   
    
    void setBy_month_months(int v)      { by_month_months = v; }
    int getBy_month_months()            { return by_month_months; }       
    
};
    
#endif

